﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Xml;

namespace Indigox.Common.Configuration
{
    public abstract class XmlConfigurator
    {
        private bool fileWatched = false;
        private FileWatcher fileWatcher;

        public void LoadFile( FileInfo file )
        {
            this.LoadFile( file, false );
        }

        public void LoadFile( FileInfo file, bool watchFile )
        {
            using ( XmlReader reader = new XmlTextReader( file.FullName ) )
            {
                this.DoLoad( reader );
            }

            if ( watchFile )
            {
                this.UnWatch();
                this.DoWatch( file );
            }
        }

        public void LoadXml( string xml )
        {
            using ( TextReader txtReader = new StringReader( xml ) )
            using ( XmlReader reader = new XmlTextReader( txtReader ) )
            {
                this.DoLoad( reader );
            }
        }

        public void LoadFromAssembly( Assembly assembly, string resourceName )
        {
            using ( Stream stream = assembly.GetManifestResourceStream( resourceName ) )
            using ( XmlReader reader = new XmlTextReader( stream ) )
            {
                this.DoLoad( reader );
            }
        }

        public void LoadFromAppConfig( string sectionName )
        {
            XmlNode node = ConfigurationManager.GetSection( sectionName ) as XmlNode;
            LoadXml( node.OuterXml );
        }

        private void OnConfigurationFileChanged( FileInfo file )
        {
            this.LoadFile( file );
        }

        protected virtual void DoLoad( XmlReader reader )
        {

        }

        private void DoWatch( FileInfo file )
        {
            this.fileWatched = true;
            this.fileWatcher = new FileWatcher( file, OnConfigurationFileChanged );
        }

        private void UnWatch()
        {
            if ( this.fileWatched )
            {
                this.fileWatched = false;
                this.fileWatcher.Dispose();
            }
        }
    }
}
